package com.ruoyi.common.utils.pay;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;

@Component
public class PoliPayService {

    private static final Logger LOG = LoggerFactory.getLogger(PoliPayService.class);

    @Value("${pay.port}")
    private int port;
    @Value("${pay.merchantCode}")
    private String merchantCode;
    @Value("${pay.authenticationCode}")
    private String authenticationCode;
    @Value("${pay.payUrl}")
    private String payUrl;
    @Value("${pay.transactionUrl}")
    private String transactionUrl;
    @Value("${pay.currencyCode}")
    private String currencyCode;
    @Value("${pay.merchantHomepageURL}")
    private String merchantHomepageURL;
    @Value("${pay.successURL}")
    private String successURL;
    @Value("${pay.failureURL}")
    private String failureURL;
    @Value("${pay.cancellationURL}")
    private String cancellationURL;
    @Value("${pay.notificationURL}")
    private String notificationURL;

    private final String METHOD_GET = "GET";
    private final String METHOD_POST = "POST";

    //发起支付
    public String startPay(BigDecimal amount, String merchantReference) {
        HttpURLConnection conn = openConn(payUrl, METHOD_POST);
        try {
            String payInfoJson = buildPayInfo(amount, merchantReference);
            OutputStream os = conn.getOutputStream();
            os.write(payInfoJson.getBytes("UTF-8"));
            os.close();
            InputStream in = new BufferedInputStream(conn.getInputStream());
            byte[] contents = new byte[1024];
            int bytesRead;
            String poliResponse = "";
            while ((bytesRead = in.read(contents)) != -1) {
                poliResponse += new String(contents, 0, bytesRead);
            }
            LOG.info("get start pay json:{}", poliResponse);
            in.close();
            return poliResponse;
        } catch (IOException ex) {
            ex.printStackTrace();
            LOG.error("call pay url failed! ex:{}", ex);
        } finally {
            conn.disconnect();
        }
        return null;
    }

    //查询支付结果
    public String getTransaction(String token) {
        String url = transactionUrl + "?token=" + token;
        HttpURLConnection conn = openConn(url, METHOD_GET);
        try {
            InputStream in = new BufferedInputStream(conn.getInputStream());
            byte[] contents = new byte[1024];
            int bytesRead = 0;
            String poliResponse = "";
            while ((bytesRead = in.read(contents)) != -1) {
                poliResponse += new String(contents, 0, bytesRead);
            }
            LOG.info("get pay transaction json:{}", poliResponse);
            in.close();
            return poliResponse;
        } catch (IOException ex) {
            ex.printStackTrace();
            LOG.error("call pay transaction failed! ex:{}", ex);
        } finally {
            conn.disconnect();
        }
        return null;
    }

    private HttpURLConnection openConn(String url, String requestMethod) {
        HttpURLConnection conn = null;
        String accesscode = merchantCode + ":" + authenticationCode;
        String encodedAuthString = Base64.getEncoder().encodeToString(accesscode.getBytes());
        try {
            URL queryUrl = new URL(url);
            conn = (HttpURLConnection) queryUrl.openConnection();
            conn.setConnectTimeout(port);
            conn.setRequestProperty("authorization", "Basic " + encodedAuthString);
            conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod(requestMethod);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return conn;
    }


    private String buildPayInfo(BigDecimal amount, String merchantReference) {
        JSONObject payInfo = new JSONObject();
        payInfo.put("Amount", amount);
        payInfo.put("CurrencyCode", currencyCode);
        payInfo.put("MerchantReference", merchantReference);
        payInfo.put("MerchantHomepageURL", merchantHomepageURL);
        payInfo.put("SuccessURL", successURL);
        payInfo.put("FailureURL", failureURL);
        payInfo.put("CancellationURL", cancellationURL);
        payInfo.put("NotificationURL", notificationURL);
        LOG.info("pay info json:{}", payInfo);
        return payInfo.toJSONString();
    }

}
